#ifndef DECK_CPP
#define DECK_CPP


#include "deck.h"
#include <vector>
#include <string>
#include <fstream>
#include "card.h"

using namespace std;


card deck::drawCard () {
	/*	Returns and removes the last card in the deck.
		Preconditions:  The deck is not empty.
		Postconditions: The last card in the deck is returned and removed from the deck.	*/

	return ( takeCard ( cardStack.size () - 1 ) );	// take the desired card out of the deck and return it
}


void deck::buildDeck ( string deckFileLocation ) {
	/*      Builds the initial deck.
		Preconditions:  The current deck is empty.
		Postconditions: The current deck is populated with the desired cards.   */

	ifstream inputDeckFile; // the deck file reader object used to load cards from the deck file
	string deckFileLine;    // line of card information loaded from the deck file
	card currentCard;

	// open the deck file for reading
	inputDeckFile.open ( deckFileLocation.c_str () );

	while ( !inputDeckFile.eof () ) {
		currentCard.clear ();   // clear out any values stored in the temporary current card
		getline ( inputDeckFile, deckFileLine );        // read the current card from the deck file

		// check for a blank line
		if ( !deckFileLine.empty () ) {
			// parse the fields out of the deckFileLine string and assign them to the currentCard object's values

			addCard ( currentCard );     // add the temporary current card to the deck
		}
	}

	inputDeckFile.close (); // close the deck file
}


card deck::takeCard ( int cardIndex ) {
	/*	Returns and removes the card at cardIndex from the deck.
		Preconditions:  The deck is not empty and contains at least cardIndex + 1 items.
		Postconditions: The specified card in the deck is returned and removed from the deck.	*/

	card takenCard = cardStack[cardIndex];	// copy the desired card
	cardStack.erase ( cardStack.begin () + cardIndex );	// destroy the original in the deck
	return ( takenCard );	// return the desired card
}


card deck::takeCard ( string name, cardColor color ) {
	/*	Returns the card matching the desired name and color.
		Preconditions:  The deck is not empty.
		Postconditions: If found, the card is returned and removed from the deck. If not, the empty card is returned.	*/
	
	int cardIter = 0;
	
	// loop until either the card is found or all cards have been checked
	while ( ( cardStack[cardIter].name != name && cardStack[cardIter].color != color ) && cardIter < cardStack.size () ) {
		cardIter++;
	}
	
	if ( cardIter < cardStack.size () ) {	// if the card was found
		return ( takeCard ( cardIter ) );	// return the card
	}
	else {	// if the card was not found
		return ( emptyCard );	// return the empty card
	}
}


void deck::shuffle () {
	/*	Shuffles the deck.
		Preconditions:  TBD
		Postconditions: The deck is shuffled.	*/
	
	// use an undetermined sort method to shuffle the deck
}


void deck::addCard ( card newCard ) {
	/*	Adds the specified card to the end of the deck.
		Preconditions:  None
		Postconditions: The specified card has been added to the end of the deck.	*/
	
	cardStack.push_back ( newCard );
}


void deck::removeCard ( int cardIndex ) {
	/*	Removes the card at cardIndex from the deck.
		Preconditions:  The deck is not empty and contains at least cardIndex + 1 items.
		Postconditions: The specified card is removed from the deck.	*/
	
	cardStack.erase ( cardStack.begin () + cardIndex );     // destroy the original in the deck
}


int deck::cardsInDeck () {
	/*	Returns the size of the deck.
		Preconditions:  None
		Postconditions: The size of the deck is returned.	*/
	
	return ( cardStack.size () );
}


bool deck::isEmpty () {
	/*	Returns true if the deck is empty and false otherwise.
		Preconditions:  None
		Postconditions: True is returned if the deck is empty, false is returned otherwise.	*/
	
	return ( cardStack.empty () );
}


string deck::thisCardName ( int cardIndex ) {
	/*	Returns the name of the card at cardIndex.
		Preconditions:  The deck is not empty and contains at least cardIndex + 1 items.
		Postconditions: The name of the card at cardIndex is returned.	*/
	
	return ( cardStack[cardIndex].name );
}


cardColor deck::thisCardColor ( int cardIndex ) {
        /*      Returns the color of the card at cardIndex.
                Preconditions:  The deck is not empty and contains at least cardIndex + 1 items.
                Postconditions: The color of the card at cardIndex is returned.  */
	
	return ( cardStack[cardIndex].color );
}


cardCategory deck::thisCardCategory ( int cardIndex ) {
        /*      Returns the category of the card at cardIndex.
                Preconditions:  The deck is not empty and contains at least cardIndex + 1 items.
                Postconditions: The category of the card at cardIndex is returned.  */
	
	return ( cardStack[cardIndex].category );
}


string deck::thisCardDescription ( int cardIndex ) {
        /*      Returns the description of the card at cardIndex.
                Preconditions:  The deck is not empty and contains at least cardIndex + 1 items.
                Postconditions: The description of the card at cardIndex is returned.  */
	
	return ( cardStack[cardIndex].description );
}

#endif
